﻿using DeviceCommon;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using DeviceControlServer;
using System.Reflection;
using System.IO;
using System.Xml;
using SuperSocket.SocketBase;
using DeviceControlServer.ServerBase;
using LogLib;
using System.Threading.Tasks;
using PipeClient;

namespace DeviceManager
{
    public partial class FormServer : Form
    {
        #region 专用于异步发送启动消息
        protected IntPtr ParentFormHandle = IntPtr.Zero;
        /// <summary>
        /// 指示是否已经通知主窗体加载完成
        /// </summary>
        protected bool _bNotified = false;
        public string AppName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
        #endregion

        /// <summary>
        /// 存储session和对应ip端口号的泛型集合
        /// </summary>
        public Dictionary<string, ClientRequestPackSession> SessionList = new Dictionary<string, ClientRequestPackSession>();

        private DeviceServer server = new DeviceServer();
        private string ipAddress_Connect;        
        private Dictionary<string, IDevice> _devices = new Dictionary<string, IDevice>();

        public FormServer()
        {
            InitializeComponent();
        }

        public FormServer(string arg)
        {
            if (!string.IsNullOrEmpty(arg))
            {
                ParentFormHandle = (IntPtr)Int32.Parse(arg);
            }
            InitializeComponent();
        }

        enum OperateType
        {
            Add = 1,  //添加
            Remove = 2  //移除
        }

        private bool InitServer()
        {
            if (server.Init())
            {
                SetMessage("服务器初始化成功!");
                server.NewSessionRequestReceived += appServer_NewRequestReceived;
                server.NewSessionConnected += appServer_NewSessionConnected;
                server.SessionClosed += appServer_SessionClosed;
                server.StateChanged += OnDeviceStateChanged;
                server.MsgResponsed += OnDeviceMsgResponsed;
                server.AppExited += OnAppExited;
                return true;
            }
            else
            {
                SetMessage(server.ErrorMessage);
                return false;
            }           
        }

        private void CloseServer()
        {         
            server.NewSessionRequestReceived -= appServer_NewRequestReceived;
            server.NewSessionConnected -= appServer_NewSessionConnected;
            server.SessionClosed -= appServer_SessionClosed;
            server.StateChanged -= OnDeviceStateChanged;
            server.MsgResponsed -= OnDeviceMsgResponsed;
            server.AppExited -= OnAppExited;
            server.Close();
            SetMessage("服务已关闭.");
        }

        private bool StartServer()
        {
            if (server.StartServer())
            {
                SetMessage("服务已启动!");
                return true;
            }
            else
            {
                SetMessage("服务启动失败!"+server.ErrorMessage);
            }
            return false;
        }

        private void StopServer()
        {
            server.Stop();
        }

        private void btn_StartListen_Click(object sender, EventArgs e)
        {
            StartServer();
        }

        private void buttonExit_Click(object sender, EventArgs e)
        {
            StopServer();
            SetMessage("服务已停止.");
        }

        private void btn_send_Click(object sender, EventArgs e)
        {
            //从客户端列获取想要发送数据的客户端的ip和端口号,然后从sessionList中获取对应session然后调用send()发送数据
            ResponseMsgPackge pack = new ResponseMsgPackge();
            pack.ActionState = DeviceActionState.Done;
            pack.DeviceName = "Camera";
            pack.Action = DeviceAction.DoAction;
            pack.Result = 9;
            pack.Success = true;
            pack.Add("Path", @"D:\Newest");         
            pack.Add("Value", "20190923");         
            server.SendPackage(pack);
        }
    
        /// <summary>
        /// 添加信息
        /// </summary>
        /// <param name="str"></param>
        private void SetMessage(string str)
        {
            try
            {
                Log.WriteAsync(str);
                richTextBox1.Invoke(new Action(() => { richTextBox1.AppendText(str + "\r\n"); }));
            }
            catch (Exception ex) { }            
        }

        /// <summary>
        /// combobox操作
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <param name="operateType">add 添加项/remove 移除项</param>
        private void ComboboxHandle(string ipAddress, OperateType operateType)
        {
            if (operateType == OperateType.Add)
            {
                cmb_socketlist.Invoke(new Action(() => { cmb_socketlist.Items.Add(ipAddress); }));
            }
            if (operateType == OperateType.Remove)
            {
                cmb_socketlist.Invoke(new Action(() => { cmb_socketlist.Items.Remove(ipAddress); }));
            }
        }

        private void LoadDevice()
        {
            //配置文件路径
            string file = Application.StartupPath + "\\Config\\" + "Devices.xml";
            DeviceConfigReader<DeviceConfig> reader = new DeviceConfigReader<DeviceConfig>(file);
            //读配置
            if (!reader.Load())
            {
                MessageBox.Show("设备配置信息加载失败!\n" + reader.ErrorMessage);
            }          
            CreatDevices(reader.ListDevices);
        }

        private void CreatDevice(DeviceConfig config, out string msg)
        {
            msg = "";
            if (config.Enable)
            {
                string dllPath = string.Format("{0}\\{1}\\{2}.dll", 
                    Application.StartupPath,
                    config.FileDirectory, 
                    config.FileName);
                if (File.Exists(dllPath))
                {
                    Assembly assembly = Assembly.LoadFile(dllPath);
                    IDevice dev = (IDevice)assembly.CreateInstance(config.TypeName);
                    if (dev != null)
                    {
                        dev.ID = config.ID;
                        dev.TimeoutMillisecond = config.Timeout;
                        _devices.Add(config.DeviceName, dev);      
                        msg = "未初始化";
                    }
                    else
                    {
                        msg = "对象创建失败";
                    }
                }
                else
                {
                    TakeLog(dllPath + "不存在.");
                    msg = "dll不存在";
                    MessageBox.Show("指定的文件路径不存在:" + dllPath);
                }
            }
            else
            {
                TakeLog("未启用该设备: " + config.DeviceName);
                msg = "未启用该设备";
            }
        }

        private void AddDeviceItemToListView(string status, DeviceConfig config)
        {
            string[] item = new string[7];
            item[0] = config.ID.ToString();
            item[1] = config.DeviceName;
            item[2] = config.ChineseDescrtiption;
            item[3] = config.Enable ? "是" : "否";
            item[4] = config.FileName;
            item[5] = config.TypeName;
            item[6] = status;
            ListViewItem lsvItem = new ListViewItem(item);
            lstDevice.Items.Insert(0, lsvItem);
        }

        private void CreatDevices(List<DeviceConfig> deviceList)
        {
            //实例化
            foreach (var config in deviceList)
            {
                string msg;
                CreatDevice(config, out msg);
                AddDeviceItemToListView(msg, config);
            }
            string info = string.Format("共加载{0}个设备", _devices.Count);
            TakeLog(info);
            server.Devices = _devices;
        }

        private void FormServer_Load(object sender, EventArgs e)
        {          
            LoadDevice();
            string msg = "";
            bool bInit = false;
            if (InitServer())
            {
                if(StartServer())
                {
                    bInit = true;
                }
                else
                {
                    msg = server.ErrorMessage;
                }
            }
            else
            {
                msg = server.ErrorMessage;
            }

            if (ParentFormHandle != IntPtr.Zero)
            {
                if (bInit)
                {
                    server.InitDevices("");
                    if (server.CheckInitResult(out msg))
                    {
                        OnAppStartupFinished();
                    }
                    else
                    {
                        OnAppStartupFinished(0, msg);
                    }
                }
                else
                {
                    OnAppStartupFinished(0, msg);
                }
            }          
        }

        private void FormServer_FormClosing(object sender, FormClosingEventArgs e)
        {
            Log.Exit();
            CloseServer();
            server.DisposeDevices("");
        }

        /// <summary>
        /// 接收连接
        /// </summary>
        /// <param name="session"></param>
        private void appServer_NewSessionConnected(ClientRequestPackSession session)
        {
            //获取远程客户端的ip端口号
            string ipAddress = session.RemoteEndPoint.ToString();
            SessionList.Add(ipAddress, session);
            ipAddress_Connect = session.RemoteEndPoint.ToString();
            ComboboxHandle(ipAddress_Connect, OperateType.Add);
            SetMessage(ipAddress_Connect + "已连接!");
        }

        /// <summary>
        /// 关闭连接
        /// </summary>
        /// <param name="session"></param>
        /// <param name="value"></param>
        private void appServer_SessionClosed(ClientRequestPackSession session, SuperSocket.SocketBase.CloseReason value)
        {
            string ipAddress = session.RemoteEndPoint.ToString();
            SessionList.Remove(ipAddress);
            ComboboxHandle(ipAddress, OperateType.Remove);
            SetMessage(ipAddress + "已关闭连接!");
        }

        /// <summary>
        /// 接收数据
        /// </summary>
        /// <param name="session"></param>
        /// <param name="requestInfo"></param>
        private void appServer_NewRequestReceived(ClientRequestPackSession session, RequestMsgPackge requestInfo)
        {
            SetMessage("设备" + requestInfo.DeviceName + "动作: " + requestInfo.Action + " " + requestInfo.InParams);
        }

        /// <summary>
        /// 执行关闭程序动作
        /// </summary>
        public void OnAppExited()
        {
            Log.WriteAsync("收到客户端的消息，开始关闭应用程序.");
            this.Close();
        }

        private void TakeLog(string strInfo)
        {
            try
            {
                if (lsbInfo.InvokeRequired)
                {
                    Action<string> outdelegate = new Action<string>(TakeLog);
                    this.BeginInvoke(outdelegate, new object[] { strInfo });
                    return;
                }

                lsbInfo.Items.Add("[" + DateTime.Now.ToString("HH:mm:ss.ffff") + "] " + strInfo);
                lsbInfo.SelectedIndex = lsbInfo.Items.Count - 1;
                Log.WriteAsync(strInfo);
            }
            catch
            {

            }
        }

     
        private void btnInit_Click(object sender, EventArgs e)
        {
            server.InitDevices("");
        }

        private void btnDoPerso_Click(object sender, EventArgs e)
        {
            IDevice device = GetSelectedDevice();
            if (device == null)
            {
                MessageBox.Show("请先选择一个设备");
                return;
            }
            string outParams = "";
            if (device.DoAction("", out outParams))
            {
                MessageBox.Show("个性化成功!\n" + outParams);
            }
            else
            {
                MessageBox.Show("个性化失败!\n" + outParams);
            }
        }

        private void btnUninit_Click(object sender, EventArgs e)
        {
            server.DisposeDevices("");
        }

        private void OnDeviceStateChanged(object sender, DeviceStateChangedEventArgs e)
        {
            IDevice device = e.Device;
            string logInfo= string.Format("设备{0}状态更新为: {1} \t{2}", device.Name, e.State, e.Message);
            TakeLog(logInfo);
        }

        private void OnDeviceMsgResponsed(object sender, DeviceMsgResponsedEventArgs e)
        {
            ResponseMsgPackge pack = e.Packge;
            UpdateDeviceActionState(pack.DeviceName, pack.ActionState);
            string logInfo = string.Format("设备{0}动作执行状态: {1} \t{2}", pack.DeviceName, pack.ActionState, pack.Message);
            TakeLog(logInfo);
        }

        private void UpdateDeviceActionState(string device, DeviceActionState state)
        {
            string stateDescription = "";
            switch (state)
            {
                case DeviceActionState.InitOK:
                    stateDescription = "初始化成功";
                    break;
                case DeviceActionState.InitFailed:
                    stateDescription = "初始化失败";
                    break;
                case DeviceActionState.ExitOK:
                    stateDescription = "卸载成功";
                    break;
                case DeviceActionState.ExitFailed:
                    stateDescription = "卸载失败";
                    break;
                case DeviceActionState.StartOK:
                    stateDescription = "启动扫描成功";
                    break;
                case DeviceActionState.StartFailed:
                    stateDescription = "启动扫描失败";
                    break;
                case DeviceActionState.StopOK:
                    stateDescription = "停止扫描成功";
                    break;
                case DeviceActionState.StopFailed:
                    stateDescription = "停止扫描失败";
                    break;
                case DeviceActionState.Done:
                    stateDescription = "动作执行成功";
                    break;
                case DeviceActionState.DoFailed:
                    stateDescription = "动作执行失败";
                    break;
                case DeviceActionState.WorkingDone:
                    stateDescription = "扫描成功";
                    break;
                case DeviceActionState.WorkingFailed:
                    stateDescription = "扫描失败";
                    break;
                case DeviceActionState.TestOK:
                    stateDescription = "测试接口成功";
                    break;
                case DeviceActionState.TestFailed:
                    stateDescription = "测试接口失败";
                    break;
                case DeviceActionState.Timeout:
                    stateDescription = "动作执行超时";
                    break;
                case DeviceActionState.CatchException:
                    stateDescription = "动作发生异常";
                    break;
                default:
                    break;
            }
            Action handler = () =>
            {
                for (int i = 0; i < lstDevice.Items.Count; i++)
                {
                    string deviceName = lstDevice.Items[i].SubItems[1].Text;
                    if (device.Equals(deviceName))
                    {
                        lstDevice.Items[i].SubItems[6].Text = stateDescription;
                        return;
                    }
                } 
            };
            this.Invoke(handler);      
        }

        private IDevice GetSelectedDevice()
        {
            if (lstDevice.SelectedItems.Count > 0)
            {
                string selectedDevice = lstDevice.SelectedItems[0].SubItems[1].Text;
                return _devices[selectedDevice];
            }
            return null;         
        }

        private void buttonOpenSettings_Click(object sender, EventArgs e)
        {
            IDevice device = GetSelectedDevice();
            if (device == null)
            {
                MessageBox.Show("请先选择一个设备");
                return;
            }
            device.ShowConfigDialog("");
        }

        private void buttonTestInterface_Click(object sender, EventArgs e)
        {
            IDevice device = GetSelectedDevice();
            if (device == null)
            {
                MessageBox.Show("请先选择一个设备");
                return;
            }
            string outParams = "";
            if (device.Test("", out outParams))
            {
                MessageBox.Show("Test成功!\n" + outParams);
            }
            else
            {
                MessageBox.Show("Test失败!\n" + outParams);
            }
        }

        /// <summary>
        /// 通知主窗体该进程启动已经完成
        /// </summary>
        protected void OnAppStartupFinished(int code = 1, string msg = "程序加载成功")
        {
            // 当父窗体为空时，不需要通知
            if (IntPtr.Zero == ParentFormHandle || _bNotified)
            {
                Log.WriteAsync(string.Format("{0}获取父进程主窗口句柄为空，不启用进程监测.", AppName));
                return;
            }
            string sendMsg = string.Format("{0}#{1}#{2}", AppName, code, msg);
            Pipe t = new Pipe(9, sendMsg, "MainStartup");
            Task.Factory.StartNew(new Action(t.run));
            Log.WriteAsync("已经通知主窗体启动完成: " + AppName);
            _bNotified = true;
        }

        private void btnDoStart_Click(object sender, EventArgs e)
        {
            IDevice device = GetSelectedDevice();
            if (device == null)
            {
                MessageBox.Show("请先选择一个设备");
                return;
            }
            string outParams = "";
            device.Start("", out outParams);
        }

        private void btnDoStop_Click(object sender, EventArgs e)
        {
            IDevice device = GetSelectedDevice();
            if (device == null)
            {
                MessageBox.Show("请先选择一个设备");
                return;
            }
            string outParams = "";
            device.Stop("", out outParams);
        }
    }
}
